﻿using System;
using System.ComponentModel;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Altairis.Web.UI.WebControls {

    [Themeable(true)]
    public class Gravatar : Control {
        private const string DEFAULT_ALTERNATE_TEXT = "Gravatar";
        private const GravatarDefaultMode DEFAULT_DEFAULT_MODE = GravatarDefaultMode.Default;
        private const GravatarRating DEFAULT_RATING = GravatarRating.G;
        private const int DEFAULT_SIZE = 80;
        private const string URL_FORMAT_HTTP = "http://www.gravatar.com/avatar/{0}?s={1}&d={2}&r={3}";
        private const string URL_FORMAT_HTTPS = "https://secure.gravatar.com/avatar/{0}?s={1}&d={2}&r={3}";

        public Gravatar() {
            this.Size = DEFAULT_SIZE;
            this.AlternateText = DEFAULT_ALTERNATE_TEXT;
            this.DefaultMode = DEFAULT_DEFAULT_MODE;
            this.Rating = DEFAULT_RATING;
        }

        [Description("Alternate text to display for avatar image.")]
        [DefaultValue(DEFAULT_ALTERNATE_TEXT), Themeable(true), Category("Appearance")]
        public string AlternateText {
            get { return (string)this.ViewState["AlternateText"]; }
            set { this.ViewState["AlternateText"] = value; }
        }

        [Description("CSS class to use")]
        [CssClassProperty, Themeable(true), Category("Appearance")]
        public string CssClass {
            get { return (string)this.ViewState["CssClass"]; }
            set { this.ViewState["CssClass"] = value; }
        }

        [Description("Image to be used in case that avatar is not defined for given e-mail address and DefaultMode is set to Custom.")]
        [UrlProperty, Themeable(true), Category("Appearance")]
        public string DefaultImageUrl {
            get { return (string)this.ViewState["DefaultImageUrl"]; }
            set { this.ViewState["DefaultImageUrl"] = value; }
        }

        [Description("Behavior in case when user has no Gravatar.")]
        [DefaultValue(DEFAULT_DEFAULT_MODE), Themeable(true), Category("Appearance")]
        public GravatarDefaultMode DefaultMode {
            get { return (GravatarDefaultMode)this.ViewState["DefaultMode"]; }
            set { this.ViewState["DefaultMode"] = value; }
        }

        [Description("E-mail address to display avatar for.")]
        [Category("Behavior")]
        public string EmailAddress {
            get { return (string)this.ViewState["EmailAddress"]; }
            set { this.ViewState["EmailAddress"] = value; }
        }

        [Description("URL to link")]
        [UrlProperty, Category("Behavior")]
        public string NavigateUrl {
            get { return (string)this.ViewState["NavigateUrl"]; }
            set { this.ViewState["NavigateUrl"] = value; }
        }

        [Description("Image censorship level.")]
        [Themeable(true), Category("Appearance"), DefaultValue(DEFAULT_RATING)]
        public GravatarRating Rating {
            get { return (GravatarRating)this.ViewState["Rating"]; }
            set { this.ViewState["Rating"] = value; }
        }

        [Description("Size of square avatar image in pixels (1-512 px).")]
        [DefaultValue(DEFAULT_SIZE), Themeable(true), Category("Appearance")]
        public int Size {
            get { return (int)this.ViewState["Size"]; }
            set {
                if (value < 1 || value > 512) throw new ArgumentOutOfRangeException("value", value, "Size must be between 1 and 80 pixels.");
                this.ViewState["Size"] = value;
            }
        }

        [Description("Tooltip text")]
        [Category("Appearance")]
        public string ToolTip {
            get { return (string)this.ViewState["ToolTip"]; }
            set { this.ViewState["ToolTip"] = value; }
        }

        protected override void Render(HtmlTextWriter writer) {
            if (this.DesignMode) {
                // Render shim in design mode
                this.RenderDesignMode(writer);
                return;
            }

            // Get URL of gravatar image
            var hash = FormsAuthentication.HashPasswordForStoringInConfigFile(this.EmailAddress ?? string.Empty, "MD5").ToLower();
            var imageUrl = URL_FORMAT_HTTP;
            if (this.Page.Request.IsSecureConnection) imageUrl = URL_FORMAT_HTTPS;
            imageUrl = string.Format(imageUrl,
                hash,                               // 0
                this.Size,                          // 1
                this.GetDefaultImageUrl(),          // 2
                this.Rating.ToString().ToLower());  // 3

            // Prepare the control to render
            Control c;
            if (string.IsNullOrWhiteSpace(this.NavigateUrl)) {
                c = new Image {
                    ImageUrl = imageUrl,
                    AlternateText = this.AlternateText,
                    ToolTip = this.ToolTip,
                    CssClass = this.CssClass,
                    Width = Unit.Pixel(this.Size),
                    Height = Unit.Pixel(this.Size)
                };
            }
            else {
                c = new HyperLink {
                    NavigateUrl = this.NavigateUrl,
                    ImageUrl = imageUrl,
                    Text = this.AlternateText,
                    ToolTip = this.ToolTip,
                    CssClass = this.CssClass,
                    Width = Unit.Pixel(this.Size),
                    Height = Unit.Pixel(this.Size),
                };
            }
            c.RenderControl(writer);
        }

        private string GetDefaultImageUrl() {
            switch (this.DefaultMode) {
                case GravatarDefaultMode.Error404:
                    return "404";
                case GravatarDefaultMode.Identicon:
                    return "identicon";
                case GravatarDefaultMode.MonsterID:
                    return "monsterid";
                case GravatarDefaultMode.Wavatar:
                    return "wavatar";
                case GravatarDefaultMode.MysteryMan:
                    return "mm";
                case GravatarDefaultMode.Retro:
                    return "retro";
                case GravatarDefaultMode.Custom:
                    // Compute real URL of default image
                    if (string.IsNullOrEmpty(this.DefaultImageUrl)) return string.Empty;
                    var ub = new UriBuilder(this.Context.Request.Url);
                    ub.Query = string.Empty;
                    ub.Path = this.Page.ResolveUrl(this.DefaultImageUrl);
                    return HttpUtility.UrlEncode(ub.Uri.ToString());
                default: // GravatarDefaultMode.Default:
                    return string.Empty;
            }
        }

        private void RenderDesignMode(HtmlTextWriter writer) {
            var c = new Image {
                AlternateText = this.AlternateText,
                ToolTip = this.ToolTip,
                CssClass = this.CssClass,
                Width = Unit.Pixel(this.Size),
                Height = Unit.Pixel(this.Size)
            };
            c.RenderControl(writer);
        }
    }
}